package com.xc58.highreactor.seril;

import static com.xc58.highreactor.util.ByteUtil.toInt;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;

import com.xc58.highreactor.exception.ParseDataException;

@SuppressWarnings({"rawtypes","unchecked"})
public class SerialMatcher {
	private static final HashMap<Class,Integer> CLASS_FLAG = new HashMap<Class,Integer>();
	private static final HashMap<Integer,ISerializer<?>> SERIAL= new HashMap<Integer, ISerializer<?>>();
	static{
		CLASS_FLAG.put(int.class, 1);
		CLASS_FLAG.put(Integer.class, 1);
		CLASS_FLAG.put(long.class, 2);
		CLASS_FLAG.put(Long.class, 2);
		CLASS_FLAG.put(short.class, 3);
		CLASS_FLAG.put(Short.class, 3);
		CLASS_FLAG.put(Character.class, 4);
		CLASS_FLAG.put(char.class, 4);
		CLASS_FLAG.put(String.class, 5);
		CLASS_FLAG.put(List.class, 6);
		/*----------serial----------*/
		SERIAL.put(1, new IntSerializer());
		SERIAL.put(2, new LongSerializer());
		SERIAL.put(3, new ShortSerializer());
		SERIAL.put(4, new CharSerializer());
		SERIAL.put(5, new StringSerializer());
		SERIAL.put(6, new ListSerializer());
		SERIAL.put(7, new ArraySerializer());
		SERIAL.put(-1, new DefaultSerializer());
	}
	protected static int getClassFlag(Class clazz){
		Integer i = CLASS_FLAG.get(clazz);
		if(i == null){
			if(clazz.isInstance(List.class)){
				CLASS_FLAG.put(clazz, 6);
				return 6;
			}else if(clazz.isArray()){
				return 7;
			}
			return -1;
		}
		return i;
	}
	
	protected static byte[] serializer(int i,Object rawObject) throws Exception{
		return ((ISerializer) SERIAL.get(i)).serialize(rawObject);
	}
	
	protected static <T> T deserializer(int i,InputStream input) throws Exception{
		return ((ISerializer<T>) SERIAL.get(i)).deserialize(input);
	}
	
	public static byte[] serializer(Object rawObject) throws Exception{
		int type = getClassFlag(rawObject.getClass());
		return ((ISerializer) SERIAL.get(type)).serialize(rawObject);
	}
	
	public static <T> T deserializer(InputStream input) throws Exception{
		byte[] btype = new byte[4];
		if(input.read(btype) < 4){
			throw new ParseDataException();
		}
		int type = toInt(btype); 
		return ((ISerializer<T>) SERIAL.get(type)).deserialize(input);
	}
	
}
